<template>
	<div>TS</div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'

const arr: Array<number | string> = [1, 2, 3, 4, 5, 6, '1']

// 泛型
interface obj {
	<T>(age: T, num: T): T
}

function fn<T>(age: T, num: T) {
	// console.log(age, num)
}
fn<string>('2', '1')

const fn2: obj = <T>(age: T, num: T): any => {
	// console.log(age, num)
}

fn2<number>(2, 1)

// 必须带有长度
interface lengthN {
	length: number
}
function myHello<T extends lengthN>(num: T) {
	// console.log(num)
}
myHello('123')
myHello([1])
myHello(1) // 报错

//定义一个用户信息的接口类型
interface User {
	age: number
	name: string
	password: string
}

type SetReadonly<T> = {
	readonly [P in keyof T]: T[P]
}
//新建只读用户数据对象
type ReadonlyUser = SetReadonly<User>
const UserInfo: ReadonlyUser = {
	age: 1,
	name: '虎克',
	password: '123456'
}
//直接报错，因为UserInfo实力中的每个属性都不可以修改
// console.log(UserInfo.password)

/* ----------------------------------------------------------------
1.使用显式类型而不是“any”
 *尽可能避免使用 any 类型，因为它会破坏 TypeScript 的优势。相反，显式定义变量、函数和参数的类型。
 *👍这样做：
 function add(a: number, b: number): number {
 	return a + b
 }
 *👎而不是这个：
 function add(a: any, b: any): any {
 	return a + b
 }

 */

/* ----------------------------------------------------------------
2. 在 tsconfig.json 中启用“严格”模式
*启用“严格”模式可确保 TypeScript 执行广泛的类型检查，从而在开发过程的早期捕获潜在的错误。
{
	“compilerOptions”: {
	“strict”: true
  	}
}
*/

/* ----------------------------------------------------------------
*3.使用只读数组
*利用只读来防止对对象和数组的意外修改。
*👍这样做：
const person: Readonly<{ name: string; age: number }> = { name: 'Alice', age: 30 };
person.age = 31; // Error: Cannot assign to 'age' because it is a read-onlyproperty
//
const numbers: ReadonlyArray<number> = [1, 2, 3];
numbers.push(4); // Error: Property 'push' does not exist on type 'readonly number[]'
*👎而不是这个：
const person = { name: 'Alice', age: 30 };
person.age = 31; // Allowed
// 
const numbers = [1, 2, 3];
numbers.push(4); // Allowed
*/

/* ----------------------------------------------------------------
*4. 使用解构来提取属性
*解构可以使您的代码更简洁、更易于阅读。
*👍这样做：
function printPersonDetails({ name, age }: { name: string; age: number }) {
  console.log(`Name: ${name}, Age: ${age}`);
}
*👎而不是这个：
function printPersonDetails(person: { name: string; age: number }) {
  console.log(`Name: ${person.name}, Age: ${person.age}`);
}
*/

/* ----------------------------------------------------------------
*5. 数组泛型优于类型转换
*使用数组泛型来指定数组中元素的类型，而不是类型转换。
*👍这样做：
const numbers: Array<number> = [1, 2, 3];
const firstNumber: number = numbers[0];
*👎而不是这个：
const numbers: any[] = [1, 2, 3];
const firstNumber: number = numbers[0] as number;
*/

/* ----------------------------------------------------------------
*6. 使用枚举作为常量
*使用枚举来表示一组相关常量，以提高代码的可读性和可维护性。
*👍这样做：
enum Fruit {
  APPLE = 'apple',
  BANANA = 'banana',
  ORANGE = 'orange',
}
*👎而不是这个：
const FRUIT_APPLE = 'apple';
const FRUIT_BANANA = 'banana';
const FRUIT_ORANGE = 'orange';
*/

/* ----------------------------------------------------------------
*7. 对于对象形状，优先选择接口而不是类型别名
*在定义对象的形状时使用接口来利用其可扩展性。
*👍这样做：
interface Person {
  name: string;
  age: number;
}
*👎而不是这个：
type Person = {
  name: string;
  age: number;
};
*/

/* ----------------------------------------------------------------
*8. 对可配置对象使用可选属性
*在接口中使用可选属性可以在配置对象时实现灵活性。
interface Person {
  name: string;
  age?: number;
}
*/

/* ----------------------------------------------------------------
*9. 使用 TypeScript 的实用类型
*利用 TypeScript 的内置实用程序类型（例如 Partial、Pick 和 Omit）来避免不必要的重复并简化代码。
interface Person {
  name: string;
  age: number;
  address: string;
}
type PartialPerson = Partial<Person>; // Makes all properties optional
type PersonName = Pick<Person, 'name'>; // Extracts a subset of properties
type PersonWithoutAge = Omit<Person, 'age'>; // Removes a property
*/

/* ----------------------------------------------------------------
*10. 对多种可能的类型使用联合类型
*使用联合类型指定一个变量可以保存多种类型的值。
function formatInput(input: string | number) {
  return `Input: ${input}`;
}
*/

/* ----------------------------------------------------------------
*11.利用交叉类型来组合类型
*使用交集类型将多种类型合并为单一类型。
*👍这样做：

interface Shape {
  color: string;
}

interface Circle {
  radius: number;
}

interface Rectangle {
  width: number;
  height: number;
}

type RedCircle = Shape & Circle;
type RedRectangle = Shape & Rectangle;

const redCircle: RedCircle = { color: 'red', radius: 5 };
const redRectangle: RedRectangle = { color: 'red', width: 10, height: 20 };
*👎而不是这个：
interface Employee {
  name: string;
  age: number;
}

interface Manager {
  teamSize: number;
}

type EmployeeManager = Employee & Manager;

const employee: EmployeeManager = { name: 'John Doe', age: 30, teamSize: 5 };
*/

/* ----------------------------------------------------------------
*12. 使用类型保护进行类型断言
*使用类型保护来缩小条件块中变量的类型范围。
*👍这样做：
function formatValue(value: string | number): string {
  if (typeof value === 'number') {
    return value.toFixed(2);
  } else if (typeof value === 'string') {
    return value.toUpperCase();
  } else {
    throw new Error('Invalid value');
  }
}
*👎而不是这个：
function processValue(value: string | number): string {
  if (typeof value === 'number') {
    return value.toFixed(2);
  } else {
    return value.toUpperCase();
  }
}
*/

/* ----------------------------------------------------------------
*13.更喜欢函数式编程技术
*利用函数式编程技术（例如不变性和纯函数）来提高代码清晰度并减少副作用。
*👍这样做：
const sum = Array.from({ length: 10 }, (_, i) => i + 1).reduce((acc, val) => acc + val, 0);
*👎而不是这个：
let sum = 0;
for (let i = 1; i <= 10; i++) {
  sum += i;
}
*/

/* ----------------------------------------------------------------
*14. 使用空合并运算符 (??)
*空值合并运算符 (??) 提供了一种处理空值或未定义值的简洁方法。
👍这样做：
const defaultValue = value ?? 'Default';
*👎而不是这个：
const defaultValue = value !== null && value !== undefined ? value : 'Default';
*/

/* ----------------------------------------------------------------
*15. 使用可选链接 (?.)
*可选链接 (?.) 简化了对可能未定义或为 null 的对象属性的访问。
*👍这样做：
const username = user?.profile?.name;
*👎而不是这个：
const username = user && user.profile && user.profile.name;
*/

/* ----------------------------------------------------------------
*16.杠杆类型推断
*利用 TypeScript 的类型推断功能来避免冗余的类型注释。
*👍这样做：
const name = 'Alice';
*👎而不是这个：
const name: string = 'Alice';
*/

/* ----------------------------------------------------------------
*17.避免深层嵌套
*利用 TypeScript 的类型推断功能来避免冗余的类型注释。
*👍这样做：
function process() {
  // Code
}
if (condition1 && condition2 && condition3) {
  process();
}
*👎而不是这个：
if (condition1) {
  if (condition2) {
    if (condition3) {
      // Code
    }
  }
}
*/

/* ----------------------------------------------------------------

*/
</script>

<style scoped lang="scss"></style>
